<?php
/**
 * ServiceFactory.php
 *
 * @package fitphp.com
 * @version {$Id$}
 * @Copyright 2009-2020 FitPHP Item.
 * @License MIT
 * @author Boolean <hongbin.hsu@qq.com> since.
 * @datetime 2017/12/3 下午8:40
 * =================================================================
 * 版权所有 (C) 2009-2020 fitphp.com，并保留所有权利。
 * 网站地址:http://www.fitphp.com/
 */
namespace FitPHP\Consul;

use GuzzleHttp\Client as GuzzleClient;
use Psr\Log\LoggerInterface;
use FitPHP\Consul\Services\Acl;
use FitPHP\Consul\Services\AclInterface;
use FitPHP\Consul\Services\Agent;
use FitPHP\Consul\Services\AgentInterface;
use FitPHP\Consul\Services\Catalog;
use FitPHP\Consul\Services\CatalogInterface;
use FitPHP\Consul\Services\Event;
use FitPHP\Consul\Services\EventInterface;
use FitPHP\Consul\Services\Health;
use FitPHP\Consul\Services\HealthInterface;
use FitPHP\Consul\Services\KV;
use FitPHP\Consul\Services\KVInterface;
use FitPHP\Consul\Services\Session;
use FitPHP\Consul\Services\SessionInterface;
use FitPHP\Consul\Services\Status;
use FitPHP\Consul\Services\StatusInterface;

final class ServiceFactory
{
    private static $services = array(
        AclInterface::class => Acl::class,
        AgentInterface::class => Agent::class,
        CatalogInterface::class => Catalog::class,
        EventInterface::class => Event::class,
        HealthInterface::class => Health::class,
        SessionInterface::class => Session::class,
        KVInterface::class => KV::class,
        StatusInterface::class => Status::class,

        AclInterface::SERVICE_NAME => Acl::class,
        AgentInterface::SERVICE_NAME => Agent::class,
        CatalogInterface::SERVICE_NAME => Catalog::class,
        EventInterface::SERVICE_NAME => Event::class,
        HealthInterface::SERVICE_NAME => Health::class,
        SessionInterface::SERVICE_NAME => Session::class,
        KVInterface::SERVICE_NAME => KV::class,
        StatusInterface::SERVICE_NAME => Status::class,
    );

    private $client;

    //静态变量保存全局实例
    private static $_instance = null;

    //私有构造函数，防止外界实例化对象
    private function __construct() {
    }

    //私有克隆函数，防止外办克隆对象
    private function __clone() {
    }

    //静态方法，单例统一访问入口
    static public function getInstance(array $options = array(), LoggerInterface $logger = null, GuzzleClient $guzzleClient = null) {
        if (is_null(self::$_instance) || !isset(self::$_instance)) {
            self::$_instance = new self ();
            self::$_instance->client = new Client($options, $logger, $guzzleClient);
        }
        return self::$_instance;
    }

    public function useService($service)
    {
        if (!array_key_exists(strtolower($service), self::$services)) {
            throw new \InvalidArgumentException(sprintf('The service "%s" is not available. Pick one among "%s".', $service, implode('", "', array_keys(self::$services))));
        }

        $class = self::$services[$service];

        return new $class($this->client);
    }
}
